/* eslint-disable jsdoc/no-restricted-syntax */
import { defineView } from "@/routers/tools.mjs";

class httpExampleCtrl {
  /**
   * @type {ng.IRequestConfig}
   */
  httpRequest = {
    method: "GET",
    url: "/api",
  };

  httpResponse = {
    /**
     * @type {number | null}
     */
    status: null,
    /**
     * @type {string | null}
     */
    data: null,
  };

  httpResponseFail = {
    /**
     * @type {string | null}
     */
    code: null,
    /**
     * @type {any}
     */
    response: null,
  };

  /**
   * @param {ng.IScope} $scope
   * @param {ng.IHttpService} $http
   * @param {ng.ITemplateCacheService} $templateCache
   * @param {ng.IWindowService} $window
   */
  constructor($scope, $http, $templateCache, $window) {
    this.$scope = $scope;
    this.$http = $http;
    this.$templateCache = $templateCache;
    this.$window = $window;
  }

  /**
   * @returns {string}
   */
  get requestURL() {
    const { url } = this.httpRequest;
    return url;
  }

  async doFetch() {
    this.httpResponseFail.code = null;
    this.httpResponseFail.response = null;
    this.httpResponse.status = null;
    this.httpResponse.data = null;
    try {
      const res = await this.$http({
        method: this.httpRequest.method,
        url: this.requestURL,
        cache: this.$templateCache,
      }).catch((err) => {
        // eslint-disable-next-line no-throw-literal
        throw {
          code: err.status,
          response: err,
        };
      });
      this.$scope.$apply(() => {
        this.httpResponse.status = res.status;
        this.httpResponse.data = res.data;
      });
    } catch (/** @type {*} */ err) {
      this.httpResponseFail.code = err.code ?? null;
      this.httpResponseFail.response = err;
    }
    this.$window.alert(this.httpResponse.data);
  }

  /**
   * @param {string} method
   * @param {string} url
   */
  updateModel(method, url) {
    this.httpRequest.method = method;
    this.httpRequest.url = url;
  }

  handleClick() {
    console.log(this);
  }

  static $inject = ["$scope", "$http", "$templateCache", "$window"];
}

/**
 * @type {DefineView}
 */
const httpExampleView = defineView({
  controller: httpExampleCtrl,
  controllerAs: "FetchController",
  template: /* HTML */ html`
    <div>
      <select
        ng-model="FetchController.httpRequest.method"
        aria-label="Request method"
      >
        <option>GET</option>
        <option>JSONP</option>
      </select>
      <input
        type="text"
        ng-model="FetchController.httpRequest.url"
        size="80"
        aria-label="URL"
        class="form-control"
      />
      <button class="btn" id="fetch-btn" ng-click="FetchController.doFetch()">
        doFetch</button
      ><br />
      <button
        class="btn"
        id="sample-get-btn"
        ng-click="FetchController.updateModel('GET', '/api')"
      >
        try sample GET
      </button>
      <button
        class="btn"
        id="sample-jsonp-btn"
        ng-click="FetchController.updateModel(
              'JSONP', '/api/hello')"
      >
        try sample JSONP
      </button>
      <button
        class="btn"
        id="invalid-jsonp-btn"
        ng-click="FetchController.updateModel('JSONP', 
                  'https://angularjs.org/doesntexist')"
      >
        Invalid JSONP
      </button>
      <pre>http status code: {{FetchController.httpResponse.status}}</pre>
      <pre>http response data: {{FetchController.httpResponse.data}}</pre>
      ${DebugButtonHTML("FetchController")}
    </div>
  `,
});

export default httpExampleView;
